package com.bosssoft.permission.centre.service.impl;

import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSON;
import com.bosssoft.permission.centre.dao.mapper.*;
import com.bosssoft.permission.centre.entity.*;
import com.bosssoft.permission.centre.pojo.dto.pcp.*;
import com.bosssoft.permission.centre.pojo.query.RoleQuery;
import com.bosssoft.permission.centre.pojo.query.UserQuery;
import com.bosssoft.permission.centre.service.RoleService;
import com.bosssoft.permission.centre.service.exception.UserCentreExceptionCode;
import com.github.pagehelper.Page;
import com.sd365.common.core.annotation.stuffer.IdGenerator;
import com.sd365.common.core.common.aop.MyPageInfo;
import com.sd365.common.core.common.exception.BusinessException;
import com.sd365.common.core.common.exception.DaoException;
import com.sd365.common.core.common.exception.code.BusinessErrorCode;
import com.sd365.common.core.context.BaseContextHolder;
import com.sd365.common.util.BeanException;
import com.sd365.common.util.BeanUtil;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import sun.rmi.runtime.Log;
import tk.mybatis.mapper.entity.Example;

import javax.validation.Valid;
import java.util.*;

/**
 * @Author: wang
 * @Time: 2022/3/24
 */
@Service
public class RoleServiceImpl extends AbstractBaseDataServiceImpl implements RoleService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private RoleResourceMapper roleResourceMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private IdGenerator idGenerator;
    @Autowired
    private ResourceMapper resourceMapper;

    @Override
    public Boolean assignResource(RoleResourceDTO roleResourceDTO) {
        try {
            //给多个角色分配多个资源
            List<Long> roleIds = roleResourceDTO.getRoleIds();
            List<Long> resourceIds = roleResourceDTO.getResourceIds();
            RoleResource roleResource = new RoleResource();

            for (Long roleId : roleIds) {
                roleResource.setRoleId(roleId);
                for (Long resourceId : resourceIds) {
                    roleResource.setResourceId(resourceId);
                    int num = roleResourceMapper.haveRoleResource(roleResource);
                    if (num == 0) {
                        roleResource.setId(idGenerator.snowflakeId());
                        super.baseDataStuff4Add(roleResource);
                        roleResource.setStatus((byte) 0);
                        roleResource.setVersion(1L);
                        int result = roleResourceMapper.insert(roleResource);
                        if (result < 0) {
                            throw new DaoException(UserCentreExceptionCode.RESOURCE_ASSIGN_FAILED, null);
                        }
                    }
                }
            }
            return true;
        } catch (Exception e) {
            throw new BusinessException(UserCentreExceptionCode.RESOURCE_ASSIGN_FAILED, e);
        }
    }

    @Override
    public Boolean assignUser(UserRoleDTO userRoleDTO) {
        try {
            //给多个角色分配多个资源
            List<Long> roleIds = userRoleDTO.getRoleIds();
            List<Long> userIds = userRoleDTO.getUserIds();
            UserRole userRole = new UserRole();

            for (Long roleId : roleIds) {
                userRole.setRoleId(roleId);
                for (Long userId : userIds) {
                    userRole.setUserId(userId);
                    int num = userRoleMapper.haveUserRole(userRole);
                    if (num == 0) {
                        userRole.setId(idGenerator.snowflakeId());
                        super.baseDataStuff4Add(userRole);
                        userRole.setStatus((byte) 0);
                        userRole.setVersion(1L);
                        int result = userRoleMapper.insert(userRole);
                        if (result < 0) {
                            throw new DaoException(UserCentreExceptionCode.RESOURCE_ASSIGN_FAILED, null);
                        }
                    }
                }
            }
            return true;
        } catch (Exception e) {
            throw new BusinessException(UserCentreExceptionCode.RESOURCE_ASSIGN_FAILED, e);
        }
    }

    @Override
    public List<Node> queryResourceByRoleId(long roleId) {
        try {
            return roleResourceMapper.queryResourceByRoleId(roleId);
        } catch (Exception ex) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_USER_CENTRE_ROLE_DB_EXCEPTION_CODE, ex);
        }
    }

    @Override
    public List<Node> selectCompany() {
        return roleMapper.selectCompany();
    }

    @Override
    public boolean haveRole(@Valid RoleDTO roleDTO) {
        Role role = BeanUtil.copy(roleDTO, Role.class);
        return roleMapper.haveRole(role) > 0;
    }

    @Override
//    @CommonFieldStuffer(methodType = MethodTypeEnum.ADD)
    public Boolean add(@Valid RoleDTO roleDTO) {
        Role role = BeanUtil.copy(roleDTO, Role.class);
        role.setId(idGenerator.snowflakeId());
        super.baseDataStuff4Add(roleDTO);
        role.setCreatedTime(new Date());
        role.setUpdatedTime(new Date());
        return roleMapper.insert(role) > 0;
    }

    @Override
//    @CommonFieldStuffer(methodType = MethodTypeEnum.DELETE)
    public Boolean remove(Long id, Long version) {
        Example exampleRole = new Example(Role.class);
        exampleRole.createCriteria().andEqualTo("id", id).andEqualTo("version", version);

        Example exampleRoleResource = new Example(RoleResource.class);
        exampleRoleResource.createCriteria().andEqualTo("roleId", id);

        Example exampleUserRole = new Example(UserRole.class);
        exampleUserRole.createCriteria().andEqualTo("roleId", id);

        roleResourceMapper.deleteByExample(exampleRoleResource);
        userRoleMapper.deleteByExample(exampleUserRole);
        return roleMapper.deleteByExample(exampleRole) > 0;

    }

    @Override
    public RoleDTO modify(RoleDTO roleDTO) {
        try {
            Role role = BeanUtil.copy(roleDTO, Role.class);
            role.setUpdatedTime(new Date());
            Example example = new Example(Role.class);
            example.createCriteria().andEqualTo("id", roleDTO.getId()).andEqualTo("version", roleDTO.getVersion());

            super.baseDataStuff4Updated(role);
            if (roleMapper.updateByExample(role, example) > 0) {
                RoleDTO roleDTOCache = BeanUtil.copy(role, RoleDTO.class);
                BeanUtil.copy(role.getCompany(), roleDTOCache.getCompanyDTO(), CompanyDTO.class);
                BeanUtil.copy(role.getOrganization(), roleDTOCache.getOrganizationDTO(), OrganizationDTO.class);
                BeanUtil.copy(role.getTenant(), roleDTOCache.getTenantDTO(), TenantDTO.class);
                return roleDTOCache;
            }
            return null;
        } catch (BeanException ex) {
            throw new BusinessException(BusinessErrorCode.SYSTEM_BEAN_COPY_EXCEPTION, ex);
        } catch (Exception ex) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_USER_CENTRE_ROLE_DB_EXCEPTION_CODE, ex);

        }

    }

    @Override
//    @CommonFieldStuffer(methodType = MethodTypeEnum.QUERY)
    public List<RoleDTO> commonQuery(RoleQuery roleQuery) {
        if (roleQuery == null) {
            throw new BusinessException(BusinessErrorCode.SYSTEM_SERVICE_ARGUMENT_NOT_VALID, new Exception("commonQuery 方法错误"));
        }
        try {
            Role role = new Role();
            role.setName(roleQuery.getName());
            role.setCompanyId(roleQuery.getCompanyId());

            List<Role> roles = roleMapper.commonQuery(role);
            Page page = (Page) roles;
            BaseContextHolder.set("pageInfo", JSON.toJSONString(new MyPageInfo(page.getTotal(), page.getPages())));

            //对象转化 po list to dto list
            List<RoleDTO> roleDTOS = BeanUtil.copyList(roles, RoleDTO.class, new BeanUtil.CopyCallback() {
                @Override
                public void copy(Object o, Object o1) {
                    // 调用 BeanUtil.copyProperties
                    if (o == null || o1 == null) {
                        throw new BeanException("拷贝对象不可以为空", new Exception("copyList 拷贝回调错误"));
                    }

                    Role roleSource = (Role) o;
                    RoleDTO roleDTO = (RoleDTO) o1;
                    BeanUtil.copy(roleSource.getCompany(), roleDTO.getCompanyDTO(), CompanyDTO.class);
                    BeanUtil.copy(roleSource.getOrganization(), roleDTO.getOrganizationDTO(), OrganizationDTO.class);
                    BeanUtil.copy(roleSource.getTenant(), roleDTO.getTenantDTO(), TenantDTO.class);


                }
            });

            return roleDTOS;
        } catch (BeanException ex) {
            throw new BusinessException(BusinessErrorCode.SYSTEM_BEAN_COPY_EXCEPTION, ex);
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_USER_CENTRE_ROLE_DB_EXCEPTION_CODE, ex);

        }
    }


    @Override
//    @CommonFieldStuffer(methodType = MethodTypeEnum.QUERY)
    public RoleDTO queryById(Long id) {
        try {
            RoleDTO roleDTO = null;
            Role role = roleMapper.selectById(id);
            if (role != null) {
                roleDTO = BeanUtil.copy(role, RoleDTO.class);
                BeanUtil.copy(role.getCompany(), roleDTO.getCompanyDTO(), CompanyDTO.class);
                BeanUtil.copy(role.getOrganization(), roleDTO.getOrganizationDTO(), OrganizationDTO.class);
                BeanUtil.copy(role.getTenant(), roleDTO.getTenantDTO(), TenantDTO.class);
            }
            return roleDTO;
        } catch (BeanException ex) {
            throw new BusinessException(BusinessErrorCode.SYSTEM_BEAN_COPY_EXCEPTION, ex);
        } catch (Exception ex) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_USER_CENTRE_ROLE_DB_EXCEPTION_CODE, ex);
        }
    }

    @Override
    public RoleDTO copy(Long id) {
//        if (null == id) {
//            throw new RuntimeException("传输参数为空异常:copy方法");
//        }
//        Role role = roleMapper.selectByPrimaryKey(id);
//        if (role != null) {
//            RoleDTO roleDTO = BeanUtil.copy(role, RoleDTO.class);
//            return roleDTO;
//        } else return new RoleDTO();

        if (null == id) {
            throw new RuntimeException("传输参数为空异常:copy方法");
        }
        Role role = roleMapper.selectById(id);
        if (role != null) {
            RoleDTO roleDTO = BeanUtil.copy(role, RoleDTO.class);
            return roleDTO;
        } else return new RoleDTO();

        /**
         查询 id的角色信息
         修改 id 插入行的角色信息
         */
    }

    @Override
//    @CommonFieldStuffer(methodType = MethodTypeEnum.DELETE)
    public Boolean batchRemove(RoleDTO[] roleDTOS) {
        Assert.notEmpty(roleDTOS, "批量删除参数不可以为空");
        for (RoleDTO roleDTO : roleDTOS) {
            Example exampleRoleResource = new Example(RoleResource.class);
            exampleRoleResource.createCriteria().andEqualTo("roleId", roleDTO.getId());
            roleResourceMapper.deleteByExample(exampleRoleResource);

            Example exampleUserRole = new Example(UserRole.class);
            exampleUserRole.createCriteria().andEqualTo("roleId", roleDTO.getId());
            userRoleMapper.deleteByExample(exampleUserRole);
        }
        for (RoleDTO roleDTO : roleDTOS) {
            Example example = new Example(Role.class);
            example.createCriteria().andEqualTo("id", roleDTO.getId()).andEqualTo("version", roleDTO.getVersion());
            int result = roleMapper.deleteByExample(example);
            Assert.isTrue(result > 0, String.format("删除的记录id %d 没有匹配到版本", roleDTO.getId()));
        }
        return true;

    }

    @Override
    public List<UserDTO> commonQueryUser(UserQuery userQuery) {
        try {
            if (userQuery == null) {
                throw new BusinessException(BusinessErrorCode.SYSTEM_SERVICE_ARGUMENT_NOT_VALID, new Exception("commonQueryUser 方法错误"));
            }
            //全部查询
            Example example = new Example(User.class);
            example.setOrderByClause("updated_time DESC");

            Example.Criteria criteria = example.createCriteria();

            if (userQuery.getCode() != null) {//模糊查询
                criteria.orLike("code", "%" + userQuery.getCode() + "%");
            } else {
                criteria.orLike("code", userQuery.getCode());
            }
            if (userQuery.getName() != null) {//模糊查询
                criteria.orLike("name", "%" + userQuery.getName() + "%");
            } else {
                criteria.orLike("name", userQuery.getName());
            }

            List<User> users = userMapper.selectByExample(example);
            Page page = (Page) users;
            BaseContextHolder.set("pageInfo", JSON.toJSONString(new MyPageInfo(page.getTotal(), page.getPages())));

            List<UserDTO> userDTOS = BeanUtil.copyList(users, UserDTO.class);
            return userDTOS;
        } catch (BeanException ex) {
            throw new BusinessException(BusinessErrorCode.SYSTEM_BEAN_COPY_EXCEPTION, ex);
        } catch (Exception ex) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_USER_CENTRE_ROLE_DB_EXCEPTION_CODE, ex);

        }
    }

    @Override
    public RoleDTO queryUserResource(Long id) {
        Role role = roleMapper.selectByPrimaryKey(id);
        Example example = new Example(RoleResource.class);
        example.selectProperties("resourceId");
        example.createCriteria().andEqualTo("roleId", id);
        List<RoleResource> roleResources = roleResourceMapper.selectByExample(example);
        Set<Long> idSet = new HashSet<>();
        for (RoleResource roleResource : roleResources) {
            idSet.add(roleResource.getResourceId());
        }
        if (!idSet.isEmpty()) {
            Example re = new Example(Resource.class);
            re.createCriteria().andIn("id", idSet);
            List<Resource> resources = resourceMapper.selectByExample(re);
            List<ResourceDTO> resourceDTOS = BeanUtil.copyList(resources, ResourceDTO.class);

            RoleDTO copy = BeanUtil.copy(role, RoleDTO.class);
            copy.setResourceDTOS(resourceDTOS);
            return copy;
        } else return null;

    }


}
